package j.util.jdbc.simple.core;

import j.data.PagedData;
import j.util.New;
import j.util.StringUtils;
import j.util.jdbc.simple.core.operations.SimpleJdbcQueryOperations;
import j.util.jdbc.simple.core.support.SimpleJdbcUtils;
import j.util.jdbc.simple.pagination.StandardPagination;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * simplejdbc查询操作，在这里提供了最基本的查询，根据pk查询详细住处，分页查询
 * 分页查询时的列表可根据查询所设置的元数据住处来获取数据，避免获取全部
 * @author 刘军海
 * @version Sep 18, 2011 12:37:15 PM
 *
 */
public class SimpleJdbcQuery extends SimpleJdbcAbstract implements
        SimpleJdbcQueryOperations {

    @Override
	public <T> T findByPk(Connection connection,Class<T> requiredType, Map<String, Object> args)throws SQLException{
		SQLData sd = this.getSqlData(requiredType);
		SQLForQuery sq = sd.getSqlQuery();
		String sql = sq.getFindByPkSql();
		if(StringUtils.isNullOrEmpty(sql)){
			throw new RuntimeException(requiredType.getName()+" entity must specify entity's pk columns.");
		}
		List<String> order = sq.getFindByPkSqlOrder();
		//将以实体属性名字为key的map转换以数据库中字段为名字的key
		Map<String,String> entityAttributeColumnMap = sd.getTmd().getEntityAttributeColumnMap();
		Map<String,Object> _args = SimpleJdbcUtils.toDbColumnKeyMap(entityAttributeColumnMap, args);
		log.debug(String.format("execute findByPk sql %s ,with values:%s.",sql,_args));
        PreparedStatement stmt = connection.prepareStatement(sql);
        SimpleJdbcUtils.setPreapredStatementParameters(sd.getTmd().getColumns(),
                stmt, order, _args);
        ResultSet rs = stmt.executeQuery();
        T t = null;
        if(rs.next()){
            t = SimpleJdbcUtils.fromResultSetToPojo(requiredType, rs, sd.getTmd().getColumns().values());
        }
        return t;
	}

	/**
	 * 以分页的形式查询，查询条件由args指定，排序由orders指定
	 */
	@Override
	public <T> PagedData<List<T>> queryList(Connection connection,Class<T> requiredType, int pageIndex,
			int pageSize, Map<String, Object> args, Map<String, String> orders) throws SQLException{
		SQLData sd = this.getSqlData(requiredType);
		SQLForQuery sq = sd.getSqlQuery();
		List<String> argsOrder = New.list(args.size());
		String sql = sq.generateQuerySql(args, orders, argsOrder);
		Object[] _args = SimpleJdbcUtils.fromMapArgsToArrayArgs(sd.getTmd().getColumns(), argsOrder, args);
		return StandardPagination.fetchPage(connection, requiredType,
                sql, _args, pageIndex, pageSize);
	}

	@Override
	public <T> List<T> queryList(Connection connection,Class<T> requiredType,
			Map<String, Object> args, Map<String, String> orders) throws SQLException{
		SQLData sd = this.getSqlData(requiredType);
		SQLForQuery sq = sd.getSqlQuery();
		List<String> argsOrder = New.list();
		String sql = sq.generateQuerySql(args, orders, argsOrder);
		//结果集
		List<T> list = New.list();
		log.debug(String.format("execute queryList with no page sql %s ,with values:%s.",sql,args));
        PreparedStatement stmt = connection.prepareStatement(sql);
        SimpleJdbcUtils.setPreapredStatementParameters(sd.getTmd().getColumns(),
                stmt, argsOrder, args);
        ResultSet rs = stmt.executeQuery();
        while(rs.next()){
            list.add(SimpleJdbcUtils.fromResultSetToPojo(requiredType, rs, sd.getTmd().getColumns().values()));
        }
        rs.close();
        stmt.close();
		return list;
	}

}
